﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace PseudoOriginalServer
{
    /// <summary>
    /// 同义词替换伪随机
    ///     词的变动应该会出现循环变化，但是替换的内容不应该出现循环变化
    /// </summary>
    public class PseudoOriginal_SynonymSubstitution : IPseudoOriginalHandler
    {
        public Dictionary<string, string> Synonym;

        public PseudoOriginal_SynonymSubstitution() { }

        public PseudoOriginal_SynonymSubstitution(string file)
        {
            Synonym = new Dictionary<string, string>();

            Retry.ByCount(() =>
            {
                using (StreamReader sr = new StreamReader(file))
                {
                    var tmp = new List<KeyValuePair<string, string>>();
                    while (sr.Peek() > 0)
                    {
                        var line = sr.ReadLine();

                        if (line.TrimStart().StartsWith("#"))
                            continue;

                        var space = line.IndexOf(" ");
                        if (space == -1)
                            continue;

                        var key = line.Substring(0, space);
                        var value = line.Substring(space + 1);
                        tmp.Add(new KeyValuePair<string, string>(key, value));
                    }

                    foreach (var item in tmp)
                        Synonym[item.Key] = item.Value;
                }
            }, 10);
        }

        public PseudoOriginal_SynonymSubstitution(Uri uri)
        {
            throw new NotImplementedException();
        }

        public PseudoOriginal_SynonymSubstitution(Dictionary<string, string> dic)
        {
            Synonym = dic ?? new Dictionary<string, string>();
        }

        /// <summary>
        /// 同义词替换处理
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public string Handle(string html)
        {
            if (string.IsNullOrEmpty(html))
                return string.Empty;

            var ranges = new List<Range<string>>();

            foreach (var item in Synonym)
            {
                var tmp = FindAll(html, item.Key);
                ranges.AddRange(tmp.Select(n => new Range<string>
                {
                    Index = n.Index,
                    Lenght = n.Lenght,
                    Item = item.Value,
                }));
            }

            var orderRange = ranges.OrderBy(n => n.Index);
            StringBuilder sb = new StringBuilder();

            var index = 0;
            foreach (var item in orderRange)
            {
                var duan_1 = html.Substring(index, item.Index - index);
                sb.Append(duan_1);
                sb.Append(item.Item);
                index = item.Index + item.Lenght;
            }

            sb.Append(html.Substring(index));

            return sb.ToString();
        }

        private List<Range> FindAll(string body, string target)
        {
            if (string.IsNullOrEmpty(body))
                return null;

            if (string.IsNullOrEmpty(target))
                return null;

            var ranges = new List<Range>();

            var index = 0;
            while (true)
            {
                var tmp = body.IndexOf(target, index);

                if (tmp == -1)
                    break;

                ranges.Add(new Range { Index = tmp, Lenght = target.Length });
                index = tmp + target.Length;
            }

            return ranges;
        }
    }
}
